﻿using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Windows.ApplicationModel.Core;
using Windows.UI.Core;
using Windows.UI.Xaml;
using com.IronOne.BoardPACWinAppBO.Agenda;
using com.IronOne.BoardPACWinAppBO.General;
using com.IronOne.BoardPACWinAppBO.Paper;
using com.IronOne.BoardPACWinAppService.Agenda;
using com.IronOne.BoardPACWinAppUtil.Security;
using com.IronOne.BoardPACWinAppUtil.Util;

// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236

namespace com.IronOne.BoardPACWinApp.View.UserControl
{
    public sealed partial class DownloadingUserControl
    {
        private static TaskCompletionSource<ResponseDataModel> _mTaskCompletionSource;
        //StorageFolder folder;
        //DownloadOperation downloadOperation;
        //CancellationTokenSource cancellationToken;
        //BackgroundDownloader backgroundDownloader = new BackgroundDownloader();

        private IAgendaService _agendaService;
        public bool IsCancelClicked;

        public DownloadingUserControl()
        {
            InitializeComponent();
            _agendaService = new AgendaService();
        }

        /// <summary>
        ///     0==used to download paper
        ///     1==used to download news and shared documents
        /// </summary>
        /// <param name="type">0==pass an agenda item | 1== pass paper model</param>
        /// <param name="globalSelectdAgendaItem"></param>
        /// <param name="paper"></param>
        /// <returns></returns>
        public async Task<ResponseDataModel> ShowAsync(int type, AgendaItem globalSelectdAgendaItem, PaperModel paper)
        {
            try
            {
                if (type == 0)
                    InitializeProcess1(globalSelectdAgendaItem);
                else
                    InitializeProcess2(paper);

                MPopup.IsOpen = true;
                MPopup.IsLightDismissEnabled = false;

                ProgressBarDownload.IsIndeterminate = true;
                TextBlockStatus.Text = "Initializing...";
                TextBlockProgress.Text = "Establishing connection to download";

                _mTaskCompletionSource = new TaskCompletionSource<ResponseDataModel>();
                var result = await _mTaskCompletionSource.Task;
                return result;
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void ClosePopup(ResponseDataModel mem)
        {
            try
            {
                ClosePopupDispatch();

                //NOTE: Download progress start and then user clicks cancel will be handled here
                if (IsCancelClicked)
                {
                    mem.IsError = true;
                    mem.ErrorCode = "-1";
                    //m_TaskCompletionSource.SetResult(mem);
                }

                _mTaskCompletionSource.SetResult(mem);
            }
            catch (Exception)
            {
                throw;
            }
        }

        private async void ClosePopupDispatch()
        {
            await
                CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                    () => { MPopup.IsOpen = false; });
        }

        public void InitializeProcess1(AgendaItem globalSelectdAgendaItem)
        {
            try
            {
                MRect1.Height = Window.Current.Bounds.Height;
                MRect1.Width = Window.Current.Bounds.Width;

                MRect2.Width = Window.Current.Bounds.Width;
                MRect2.Height = Window.Current.Bounds.Height * 0.3;

                var link = Global.ServerUrl + string.Format(RequestURL.DocumentDownloadForce,
                    globalSelectdAgendaItem.MeetingId,
                    globalSelectdAgendaItem.DocType,
                    globalSelectdAgendaItem.Id,
                    globalSelectdAgendaItem.VersionId,
                    globalSelectdAgendaItem.Id);

                var url = new Uri(link);
                DownloadFile(url);
            }
            catch (Exception)
            {
                throw;
            }
        }

        public void InitializeProcess2(PaperModel paper)
        {
            try
            {
                MRect1.Height = Window.Current.Bounds.Height;
                MRect1.Width = Window.Current.Bounds.Width;

                MRect2.Width = Window.Current.Bounds.Width;
                MRect2.Height = Window.Current.Bounds.Height * 0.30;

                var link = Global.ServerUrl + string.Format(RequestURL.NewsOrSharedItemDownloadForce,
                    paper.PaperId,
                    paper.DocType,
                    paper.PaperId);

                var url = new Uri(link);
                DownloadFile(url);
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void ButtonCloseCancel_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                IsCancelClicked = true;
                _request.Abort();
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void UserControl_Unloaded(object sender, RoutedEventArgs e)
        {
            _agendaService = null;
        }

        #region Download File

        private HttpWebRequest _request;
        private IAsyncResult _responseAsyncResult;

        private void DownloadFile(Uri url)
        {
            try
            {
                _request = WebRequest.Create(url) as HttpWebRequest;
                if (_request == null) return;

                _request.Method = ApplicationConstants.RequestType.GET;
                _request.CookieContainer = _agendaService.GetCookieContainer();
                _request.ContentType = "application/x-www-form-urlencoded";
                _request.Headers["X-deviceId"] = DeviceService.GetAppSpecificHardwareId();
                _request.Headers["X-clientTime"] = Utility.GetDateAsString(DateTime.Now);
                _request.Headers["X-clientAppVersion"] = DeviceService.GetAppVersion();
                _request.Headers["X-cooperateId"] = "1";

                _responseAsyncResult = _request.BeginGetResponse(DownloadFileResponseCallback, null);
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void DownloadFileResponseCallback(object state)
        {
            try
            {
                var response = _request.EndGetResponse(_responseAsyncResult) as HttpWebResponse;
                var contentLength = response.ContentLength;
                if (contentLength == -1)
                {
                    // You'll have to figure this one out.
                }
                var responseStream = response.GetResponseStream();
                var data = DownloadFileProgressReporting(responseStream, contentLength);
                ClosePopup(new ResponseDataModel { Data = data });
            }
            catch (Exception e)
            {
                var rdm = new ResponseDataModel();
                if (IsCancelClicked)
                    rdm.ErrorCode = "-1";

                rdm.IsError = true;
                rdm.ErrorMessage = "Paper downloading error\n" + e.Message;
                ClosePopup(rdm);
            }
        }

        private byte[] DownloadFileProgressReporting(Stream responseStream, long contentLength)
        {
            var data = new byte[contentLength];
            try
            {
                ProgressBarInitialize();
                DownloadFileProgressBarUpdate(0, 0, 0);

                // Allocate space for the content                
                var currentIndex = 0;
                var buffer = new byte[256];
                do
                {
                    var bytesReceived = responseStream.Read(buffer, 0, 256);
                    Array.Copy(buffer, 0, data, currentIndex, bytesReceived);
                    currentIndex += bytesReceived;

                    // Report percentage
                    var percentage = (double)currentIndex / contentLength;
                    DownloadFileProgressBarUpdate((int)(percentage * 100), bytesReceived, (int)contentLength);
                } while (currentIndex < contentLength);

                DownloadFileProgressBarUpdate(100, 0, 0);
            }
            catch (Exception)
            {
            }
            return data;
        }

        private async void ProgressBarInitialize()
        {
            await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                TextBlockStatus.Text = "Downloading...";
                TextBlockProgress.Text = "";
                ProgressBarDownload.IsIndeterminate = false;
            });
        }

        private async void DownloadFileProgressBarUpdate(int percentage, int received, int totalBytes)
        {
            await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                try
                {
                    if (received == 0 && totalBytes == 0)
                        TextBlockProgress.Text = "";
                    else
                        TextBlockProgress.Text = String.Format("{0}% complete.", percentage);
                    ProgressBarDownload.Value = percentage;
                    if (percentage == 100)
                        ButtonCloseCancel.IsEnabled = false;
                }
                catch (Exception)
                {
                }
            });
        }

        #endregion
    }
}